package cordova.plugin.bugly;

import android.annotation.TargetApi;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.provider.Settings;
import android.support.multidex.MultiDex;
import android.util.Log;

import com.tencent.bugly.Bugly;
import com.tencent.bugly.CrashModule;
import com.tencent.bugly.beta.Beta;
import com.tencent.bugly.crashreport.CrashReport;
import com.tencent.tinker.entry.DefaultApplicationLike;

import org.apache.cordova.BuildConfig;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class BuglyApplicationLike extends DefaultApplicationLike {

    public static final String TAG = "BuglyApplicationLike";

    public static final String HPOS_DIR = "/sdcard/Download/hpos";

    /**
     * appId替换成你的在Bugly平台申请的appId
     */
    public static final String APP_ID = "5e3a1269f1";

    public BuglyApplicationLike(Application application, int tinkerFlags,
                                boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime,
                                long applicationStartMillisTime, Intent tinkerResultIntent) {
        super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
    }

    private JSONObject getDeviceInfo(File deviceInfoFile){
        Scanner scanner = null;
        JSONObject deviceInfo = new JSONObject();

        try{
            if(deviceInfoFile.exists()){
                StringBuffer sb = new StringBuffer();
                scanner = new Scanner(deviceInfoFile);
                while(scanner.hasNextLine()){
                    sb.append(scanner.nextLine());
                }
                scanner.close();
                deviceInfo = new JSONObject(sb.toString());
            }
        }catch (Exception e){
            Log.e(TAG, "read deviceInfo.json error");
        }finally {
            if(scanner != null){
                scanner.close();
            }
        }
        return deviceInfo;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        try{
            // 读取程序目录的deviceInfo
            File appDir = getApplication().getFilesDir();
            File deviceInfoFile = new File(appDir
                    + "/www/nodejs-project/static/deviceInfo/deviceInfo.json");

            // 错误上报
            String deviceId = Settings.Secure.getString(getApplication().getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
            String manufacturer = android.os.Build.MANUFACTURER;
            String model = android.os.Build.MODEL;
            JSONObject deviceInfo = getDeviceInfo(deviceInfoFile);
            String version = deviceInfo.optString("applicationVersion");
            version = "".equals(version) ? "V1.0.0" : version;
            String channel = deviceInfo.optString("serverEnv");
            channel = "".equals(channel) ? "default" : channel;

            CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(getApplication());
            strategy.setAppChannel(channel);
            strategy.setAppVersion(version);
            strategy.setAppReportDelay(5000);
            strategy.setDeviceID(deviceId);
            // strategy.setEnableCatchAnrTrace(true);
            // strategy.setEnableANRCrashMonitor(true);
            // strategy.setEnableNativeCrashMonitor(true);
            strategy.setCrashHandleCallback(new CrashReportHandler());

            // 将第三个参数改为true,可打印出TINKER_ID
            Bugly.init(getApplication(), APP_ID, true, strategy);
            Log.i(TAG, "Init bugly crash_report and  app_upgrade.");

            // CrashReport.setIsDevelopmentDevice(getApplication(), BuildConfig.DEBUG);
            // CrashReport.initCrashReport(getApplication(), APP_ID, true, strategy);
            // Log.i(TAG, "Init bugly crash report.");

            // 检查闪退文件并上报
            checkErrorAndSendReport();

        }catch (Exception e){
            Log.e(TAG, "Bugly init error.", e);
        }

    }

    /**
     * 检查闪退文件并上报
     */
    private void checkErrorAndSendReport(){
        Log.i(TAG, "check flash exit file");
        File errorFile = new File(HPOS_DIR + "/error.lock");
        if(errorFile.exists()){
            // postCatchedException不启作用
            // CrashReport.postCatchedException(new Exception("flash exit occurred when staring app"));
            CrashReport.postException(
                    4,
                    "Flash Exit",
                    "flash-exit file exists when staring app.",
                    this.getClass().getName() + ".checkErrorAndSendReport",
                    new LinkedHashMap<String, String>()
            );
        }else{
            try{
                errorFile.createNewFile();
            }catch (Exception e){
                Log.e(TAG, "create flash-exit file error.");
            }
        }
    }

    private class CrashReportHandler extends CrashReport.CrashHandleCallback {
        public Map<String, String> onCrashHandleStart(
                int crashType, String errorType,
                String errorMessage, String errorStack) {

            Log.i(TAG, "onCrashHandleStart start");
            // 读取用户目录的deviceInfo
            File deviceInfoFile = new File(HPOS_DIR + "/deviceInfo/deviceInfo.json");
            JSONObject deviceInfo = getDeviceInfo(deviceInfoFile);
            LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
            map.put("storeCode", deviceInfo.optString("storeCode"));
            map.put("storeName", deviceInfo.optString("storeName"));
            map.put("deviceNo", deviceInfo.optString("deviceNo"));
            map.put("deviceSn", deviceInfo.optString("deviceSn"));
            return map;
        }

        @Override
        public byte[] onCrashHandleStart2GetExtraDatas(
                int crashType, String errorType,
                String errorMessage, String errorStack) {

            Log.i(TAG, "onCrashHandleStart2GetExtraDatas start");
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String logDir = HPOS_DIR + "/logs/CounterLogs/" + dateFormat.format(new Date());
            File logcat = new File(logDir, "catLog.log");
            try {
                // 倒着读300行日志
                String logs = FileUtil.getLatestLogText(logcat, 300);
                return logs.getBytes("UTF-8");
            } catch (Exception e){
                Log.e(TAG, "read catLog.log file error", e);
            }
            return null;
        }
    }


    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    @Override
    public void onBaseContextAttached(Context base) {
        super.onBaseContextAttached(base);
        // you must install multiDex whatever tinker is installed!
        MultiDex.install(base);

        // 安装tinker
        // TinkerManager.installTinker(this); 替换成下面Bugly提供的方法
        Beta.installTinker(this);
    }

    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    public void registerActivityLifecycleCallback(Application.ActivityLifecycleCallbacks callbacks) {
        getApplication().registerActivityLifecycleCallbacks(callbacks);
    }

}
